import { createCrypto, EncryptMethod, EncryptResult } from './crypto'

// 存储配置接口
interface StorageConfig {
  encrypt?: boolean
  masterPassword?: string
  encryptMethod?: EncryptMethod
}

// 默认配置
const defaultConfig: StorageConfig = {
  encrypt: false
}

/**
 * 安全存储工具类
 */
export class SecureStorage {
  private config: StorageConfig
  private crypto?: ReturnType<typeof createCrypto>

  constructor(config: StorageConfig = {}) {
    this.config = { ...defaultConfig, ...config }

    if (this.config.encrypt && this.config.masterPassword) {
      this.crypto = createCrypto({
        method: this.config.encryptMethod || EncryptMethod.AES_256_GCM,
        masterPassword: this.config.masterPassword
      })
    }
  }

  /**
   * 设置数据
   */
  setItem(key: string, value: any): void {
    try {
      let data = JSON.stringify(value)

      // 如果启用加密
      if (this.config.encrypt && this.crypto) {
        const encrypted = this.crypto.encrypt(data)
        data = JSON.stringify({
          __encrypted: true,
          ...encrypted
        })
      }

      uni.setStorageSync(key, data)

    } catch (error) {
      console.error('存储数据失败:', error)
      throw new Error('存储数据失败')
    }
  }

  /**
   * 获取数据
   */
  getItem<T = any>(key: string, defaultValue?: T): T | undefined {
    try {
      const data = uni.getStorageSync(key)

      if (!data) {
        return defaultValue
      }

      let parsedData = JSON.parse(data)

      // 如果是加密数据
      if (parsedData.__encrypted && this.crypto) {
        const encryptResult: EncryptResult = {
          encrypted: parsedData.encrypted,
          method: parsedData.method,
          version: parsedData.version,
          salt: parsedData.salt,
          iv: parsedData.iv
        }

        const decrypted = this.crypto.decrypt(encryptResult)
        parsedData = JSON.parse(decrypted)
      }

      return parsedData

    } catch (error) {
      console.error('读取数据失败:', error)
      return defaultValue
    }
  }

  /**
   * 删除数据
   */
  removeItem(key: string): void {
    try {
      uni.removeStorageSync(key)
    } catch (error) {
      console.error('删除数据失败:', error)
    }
  }

  /**
   * 清空所有数据
   */
  clear(): void {
    try {
      uni.clearStorageSync()
    } catch (error) {
      console.error('清空数据失败:', error)
    }
  }

  /**
   * 获取所有键名
   */
  getAllKeys(): string[] {
    try {
      const info = uni.getStorageInfoSync()
      return info.keys
    } catch (error) {
      console.error('获取键名失败:', error)
      return []
    }
  }

  /**
   * 获取存储信息
   */
  getStorageInfo() {
    try {
      return uni.getStorageInfoSync()
    } catch (error) {
      console.error('获取存储信息失败:', error)
      return { keys: [], currentSize: 0, limitSize: 0 }
    }
  }

  /**
   * 更新加密配置
   */
  updateConfig(config: StorageConfig) {
    this.config = { ...this.config, ...config }

    if (this.config.encrypt && this.config.masterPassword) {
      this.crypto = createCrypto({
        method: this.config.encryptMethod || EncryptMethod.AES_256_GCM,
        masterPassword: this.config.masterPassword
      })
    } else {
      this.crypto = undefined
    }
  }

  /**
   * 迁移数据（重新加密）
   */
  async migrateData(newConfig: StorageConfig) {
    try {
      const keys = this.getAllKeys()
      const data: Record<string, any> = {}

      // 读取所有数据
      for (const key of keys) {
        data[key] = this.getItem(key)
      }

      // 更新配置
      this.updateConfig(newConfig)

      // 重新存储数据
      for (const [key, value] of Object.entries(data)) {
        this.setItem(key, value)
      }

    } catch (error) {
      console.error('数据迁移失败:', error)
      throw new Error('数据迁移失败')
    }
  }
}

// 默认存储实例
let defaultStorage: SecureStorage | null = null

/**
 * 获取默认存储实例
 */
export const getStorage = (): SecureStorage => {
  if (!defaultStorage) {
    defaultStorage = new SecureStorage()
  }
  return defaultStorage
}

/**
 * 初始化安全存储
 */
export const initSecureStorage = (config: StorageConfig) => {
  defaultStorage = new SecureStorage(config)
  return defaultStorage
}

// 便捷方法
export const storage = {
  set: (key: string, value: any) => getStorage().setItem(key, value),
  get: <T = any>(key: string, defaultValue?: T) => getStorage().getItem<T>(key, defaultValue),
  remove: (key: string) => getStorage().removeItem(key),
  clear: () => getStorage().clear(),
  keys: () => getStorage().getAllKeys(),
  info: () => getStorage().getStorageInfo()
}

// 账号数据存储（特殊处理）
export const accountStorage = {
  /**
   * 保存账号数据
   */
  saveAccount: (account: any, crypto: ReturnType<typeof createCrypto>) => {
    const encrypted = {
      ...account,
      username_encrypted: account.username ? crypto.encrypt(account.username) : null,
      password_encrypted: account.password ? crypto.encrypt(account.password) : null,
      notes_encrypted: account.notes ? crypto.encrypt(account.notes) : null
    }

    // 移除明文字段
    delete encrypted.username
    delete encrypted.password
    delete encrypted.notes

    return encrypted
  },

  /**
   * 读取账号数据
   */
  loadAccount: (encryptedAccount: any, crypto: ReturnType<typeof createCrypto>) => {
    const account = { ...encryptedAccount }

    try {
      if (account.username_encrypted) {
        account.username = crypto.decrypt(account.username_encrypted)
      }

      if (account.password_encrypted) {
        account.password = crypto.decrypt(account.password_encrypted)
      }

      if (account.notes_encrypted) {
        account.notes = crypto.decrypt(account.notes_encrypted)
      }

      // 移除加密字段
      delete account.username_encrypted
      delete account.password_encrypted
      delete account.notes_encrypted

    } catch (error) {
      console.error('解密账号数据失败:', error)
      throw new Error('解密账号数据失败，请检查主密码')
    }

    return account
  }
}